home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / madness / madness.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  18KB  |  830 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  *  Copyright (c) 1988-1993 Ronald Joe Record                           *
  4.  *                                                                       *
  5.  *  All rights reserved. No part of this program or publication may be   *
  6.  *  reproduced, transmitted, transcribed, stored in a retrieval system,  *
  7.  *  or translated into any language or computer language, in any form or *
  8.  *  by any means, electronic, mechanical, magnetic, optical, chemical,   *
  9.  *  biological, or otherwise, without the prior written permission of:   *
  10.  *                                                                       *
  11.  *      Ronald Joe Record (408) 458-3718                                 *
  12.  *      212 Owen St., Santa Cruz, California 95062 USA                   *
  13.  *                                                                       *
  14.  *************************************************************************/
  15.  
  16. /*
  17.  *
  18.  *    Written 4/22 1988 by Ron Record (sco!rr)
  19.  *    Based in part on the Computer Recreations article in the 5/88
  20.  *    Scientific American.
  21.  *    
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <values.h>
  26. #include <fcntl.h>
  27. #include <math.h>
  28. #include <signal.h>
  29. #include <sys/types.h>
  30. #include <macros.h>
  31. #include <X11/StringDefs.h>
  32. #include <X11/Intrinsic.h>
  33. #include <X11/keysym.h>
  34. #include <Xm/Xm.h>
  35. #include <Xm/Form.h>
  36. #include <Xm/PushB.h>
  37. #include <Xm/DrawingA.h>
  38. #include <Xm/ToggleB.h>
  39. #include <X11/Xutil.h>
  40. #include <X11/Xatom.h>
  41.  
  42. #define ABS(a)    (((a)<0) ? (0-(a)) : (a) )
  43. #define BANDSIZ 7
  44. #define PROB 0.15
  45.  
  46. #define Min(x,y) ((x < y)?x:y)
  47. #define Max(x,y) ((x > y)?x:y)
  48.  
  49. XtEventHandler getkey();
  50.  
  51. int i, j, x_center, y_center, col=1, upper=1;
  52.  
  53. typedef struct {
  54.     int x, y;
  55. } xy_t;
  56.  
  57. typedef struct {
  58.     int left, right, top, bottom;
  59. } lrtb_t;
  60.  
  61. /* maximum number of colors allowed */
  62. #define MAXCOLOR  256
  63.  
  64. /* minimum (and default) window size */
  65. #define MIN_WIDTH 400
  66. #define MIN_HEIGHT 300
  67.  
  68. GC Data_GC[MAXCOLOR];
  69.  
  70. int    width=MIN_WIDTH, height=MIN_HEIGHT;
  71. int    numcolors=16;
  72. int hstart, hend, hmid, xwid, K=0, delay=0;
  73. extern double sin(), cos(), exp(), drand48(), atof();
  74.  
  75. double slope;
  76. double A;
  77. double stepsiz=0.01;
  78. double THETA=M_PI/12.0;
  79. double a, b, c, d, e, f, g, h;
  80. double rad;
  81. int cflag=0;
  82. int eflag=1;
  83. int Dflag=0;
  84. int Pflag=0;
  85. int heart=0;
  86. int logspiral=0;
  87. int spiral=0;
  88. int rotate=0;
  89. int hcolor, color, color2, color3, color4, color5, color6, color7, color8;
  90. int line_color;
  91. int ncols;
  92. int sflag=0;
  93. int x0, x1, xx, yy;
  94. int xy[4], save_xy[4];
  95. int x_center, y_center;
  96. int prob=0;
  97. static int num_pics=MAXSHORT;
  98. char parameter;
  99. long Radius;
  100. long nsteps=MAXLONG, numloops;
  101. Screen*     screen;
  102. Display*    dpy;
  103. char*       displayname = 0;
  104.  
  105. Widget framework, canvas, button[4];
  106. XtWorkProcId work_proc_id = (XtWorkProcId)NULL;
  107.  
  108. void     resize();
  109. void     redisplay();
  110. void     clear();
  111. void     quit();
  112. void     start_iterate();
  113. void     next_color();
  114. Boolean  draw_madness();
  115. Boolean appDefaultsFileInstalled=False;
  116.  
  117. main(argc, argv)
  118. int argc;
  119. char *argv[];
  120. {
  121.  
  122.     a = 0.3; b = 0.99; c = -0.7; d = 3.01; 
  123.     e = 0.9; f = 1.01; g = 0.1; h = 15.03;
  124.     parseargs(argc, argv);
  125.     init_motif(argc, argv);
  126.     XtMainLoop();
  127. }
  128.  
  129. setup() {
  130.  
  131.     if (++K > num_pics) {
  132.         XtCloseDisplay(dpy);
  133.         exit(0);
  134.     }
  135.     line_color = color;
  136.     rad = 0.0;
  137.     if (spiral||logspiral) {
  138.         xy[0] = x_center;
  139.         xy[1] = y_center;
  140.     }
  141.     else if (heart) {
  142.         xy[0] = 0;
  143.         xy[1] = y_center;
  144.     }
  145.     else {
  146.         xy[0]=(((a*sin(b*rad))+(c*cos(d*rad)))*x_center) + x_center;
  147.         xy[1]=(((e*sin(f*rad))+(g*cos(h*rad)))*y_center) + y_center;
  148.     }
  149.     numloops=0;
  150. }
  151.  
  152. restart() {
  153.  
  154.     setup();
  155.     if (cflag) {
  156.         switch(parameter) {
  157.                case 'a':
  158.                    a += stepsiz;
  159.                    c -= stepsiz;
  160.                    break;
  161.                case 'b':
  162.                    b += stepsiz;
  163.                    break;
  164.             case 'c':
  165.                 c += stepsiz;
  166.                    a -= stepsiz;
  167.                    break;
  168.             case 'd':
  169.                  d += stepsiz;
  170.                 break;
  171.             case 'e':
  172.                  e += stepsiz;
  173.                    g -= stepsiz;
  174.                    break;
  175.             case 'f':
  176.                 f += stepsiz;
  177.                 break;
  178.             case 'g':
  179.                 g += stepsiz;
  180.                 e -= stepsiz;
  181.                 break;
  182.             case 'h':
  183.                 h += stepsiz;
  184.                 break;
  185.         }
  186.     }
  187.     color++;
  188.     if (color == numcolors)
  189.         color=2;
  190.     if (sflag) {
  191.         setcolors();
  192.     }
  193.     if (eflag)
  194.         clear(canvas, NULL);
  195. }
  196.  
  197. Boolean
  198. draw_madness() {
  199.  
  200.     static int i, j;
  201.     xy_t p0, p1;
  202.     double run;
  203.  
  204.     if (++numloops >= nsteps) {
  205.         restart();
  206.         return TRUE;
  207.     }
  208.     if ((rand() % 100) < prob) {
  209.         hcolor = color = color2 = (rand() % (numcolors-2))+2;
  210.         if (sflag)
  211.             setcolors();
  212.         line_color = color;
  213.     }
  214.     rad = numloops*stepsiz;
  215.     if (spiral) {
  216.         xy[2] = ((a*rad*cos(rad))*x_center) + x_center;
  217.         xy[3] = ((a*rad*sin(rad))*y_center) + y_center;
  218.     }
  219.     else if (logspiral) {
  220.         xy[2] = (((exp(a*rad)-1.0)*cos(rad))*x_center) + x_center;
  221.         xy[3] = (((exp(a*rad)-1.0)*sin(rad))*y_center) + y_center;
  222.     }
  223.     else if (heart) {
  224.         xy[2] = stepsiz + xy[0];
  225.         if (xy[2] >= width - stepsiz) {
  226.             restart();
  227.             return FALSE;
  228.         }
  229.         if ((numloops % BANDSIZ) == 0) {
  230.             color++;
  231.             if (color == numcolors)
  232.                 color=2;
  233.             line_color = color;
  234.         }
  235.         if (xy[2] < hstart)
  236.             line_color = hcolor;
  237.         else if (xy[2] > hend)
  238.             line_color = hcolor;
  239.         if ((xy[2] < hstart) || (xy[2] > hend)) {
  240.             A = drand48();
  241.             xy[3]=A*(y_center/4)+y_center-(y_center/8);
  242.         }
  243.         else if (xy[2] < hmid) {
  244.             if (upper)
  245.                 A = y_center+circ(xy[2],x0);
  246.             else
  247.                 if (xy[2] < (hmid-2*xwid))
  248.                     A = y_center-circ(xy[2],x0);
  249.                 else
  250.                     A = y_center-(xy[2]-hmid)-3*xwid;
  251.             xy[3]=height - A;
  252.             if (drand48() > PROB)
  253.                 upper=!upper;
  254.         }
  255.         else {
  256.             if (upper)
  257.                 A = y_center+circ(xy[2],x1);
  258.             else
  259.                 if (xy[2] > (hmid+2*xwid))
  260.                     A = y_center-circ(xy[2],x1);
  261.                 else
  262.                     A = y_center+(xy[2]-hmid)-3*xwid;
  263.             xy[3]=height - A;
  264.             if (drand48() > PROB)
  265.                 upper=!upper;
  266.         }
  267.     }
  268.     else {
  269.         xy[2]=(((a*sin(b*rad))+(c*cos(d*rad)))*x_center) + x_center;
  270.         xy[3]=(((e*sin(f*rad))+(g*cos(h*rad)))*y_center) + y_center;
  271.     }
  272.     if (spiral || logspiral)
  273.         if ((ABS(xy[2]) > width-2) ||
  274.             (ABS(xy[3]) > height) || (min(xy[2],xy[3]) < 0))
  275.             return FALSE;
  276.     if (sflag) {
  277.         if ((run = xy[2]-xy[0]) == 0)
  278.             slope = MAXDOUBLE;
  279.         else
  280.             slope = (xy[3]-xy[1])/run;
  281.         setline();
  282.     }
  283.     if (rotate) {
  284.         save_xy[0] = xy[0]; save_xy[1] = xy[1];
  285.         save_xy[2] = xy[2]; save_xy[3] = xy[3];
  286.         xx = xy[2] - x_center; yy = xy[3] - y_center;
  287.         xy[2] = (xx*cos(K*THETA)) - (yy*sin(K*THETA));
  288.         xy[3] = (xx*sin(K*THETA)) + (yy*cos(K*THETA));
  289.         xy[2] = xy[2] + x_center; xy[3] = xy[3] + y_center;
  290.         xx = xy[0] - x_center; yy = xy[1] - y_center;
  291.         xy[0] = (xx*cos(K*THETA)) - (yy*sin(K*THETA));
  292.         xy[1] = (xx*sin(K*THETA)) + (yy*cos(K*THETA));
  293.         xy[0] = xy[0] + x_center; xy[1] = xy[1] + y_center;
  294.     }
  295.     if (in_window()) {
  296.         p0.x = xy[0]; p0.y = xy[1]; p1.x = xy[2]; p1.y = xy[3];
  297.         XDrawLine(dpy, XtWindow(canvas), Data_GC[line_color], 
  298.                 p0.x, p0.y, p1.x, p1.y);
  299. #ifdef USE_DELAY
  300.         Timer(delay);
  301. #endif
  302.     }
  303.     if (rotate) {
  304.         xy[0] = save_xy[0]; xy[1] = save_xy[1];
  305.         xy[2] = save_xy[2]; xy[3] = save_xy[3];
  306.     }
  307.     xy[0] = xy[2]; xy[1] = xy[3];
  308.     if (heart) {
  309.         xy[2] += stepsiz;
  310.         if (xy[2] >= width - stepsiz) {
  311.             restart();
  312.             return FALSE;
  313.         }
  314.         xy[3] = y_center;
  315.         if (rotate) {
  316.             save_xy[0] = xy[0]; save_xy[1] = xy[1];
  317.             save_xy[2] = xy[2]; save_xy[3] = xy[3];
  318.             xx = xy[2] - x_center; yy = xy[3] - y_center;
  319.             xy[2] = (xx*cos(K*THETA)) - (yy*sin(K*THETA));
  320.             xy[3] = (xx*sin(K*THETA)) + (yy*cos(K*THETA));
  321.             xy[2] = xy[2] + x_center; xy[3] = xy[3] + y_center;
  322.             xx = xy[0] - x_center; yy = xy[1] - y_center;
  323.             xy[0] = (xx*cos(K*THETA)) - (yy*sin(K*THETA));
  324.             xy[1] = (xx*sin(K*THETA)) + (yy*cos(K*THETA));
  325.             xy[0] = xy[0] + x_center; xy[1] = xy[1] + y_center;
  326.         }
  327.         if (in_window()) {
  328.             p0.x = xy[0]; p0.y = xy[1]; p1.x = xy[2]; p1.y = xy[3];
  329.             XDrawLine(dpy, XtWindow(canvas), Data_GC[line_color], 
  330.                 p0.x, p0.y, p1.x, p1.y);
  331. #ifdef USE_DELAY
  332.             Timer(delay);
  333. #endif
  334.         }
  335.         if (rotate) {
  336.             xy[0] = save_xy[0]; xy[1] = save_xy[1];
  337.             xy[2] = save_xy[2]; xy[3] = save_xy[3];
  338.         }
  339.         xy[0] = xy[2]; xy[1] = xy[3];
  340.     }
  341.     return FALSE;
  342. }
  343.  
  344. usage()
  345. {
  346.     printf("Usage: madness [-uAELRS] [-C parm] [-n steps] [-I size]\n");
  347.     printf("\t[-N pics] [-T div] [-W width] [-H height]\n");
  348.     printf("\t\t[-abczefgh num] [-s ncols]\n");
  349.     printf("\twhere :\n\t-u\tdisplays this message\n");
  350.     printf("\t-E\tdoesn't erase each picture\n");
  351.     printf("\t-A\tdraws the earthquake relief logo\n");
  352.     printf("\t-L\tdraws logarithmic spirals (r,@) where r = exp(a*@)\n");
  353.     printf("\t-S\tdraws spirals of the form (r,@) where r = a*@\n");
  354.     printf("\t-C parm increments the specified parameter (a-h) each picture\n");
  355.     printf("\t-R\trotates each successive picture by pi/12\n");
  356.     printf("\t-T div\tsets to angle of rotation to M_PI/div\n");
  357.     printf("\tsteps\tindicates the number of steps in each picture\n");
  358.     printf("\tpics\tindicates the number of pictures in each run\n");
  359.     printf("\tsize indicates the parametric increment at each step\n");
  360.     printf("\tncols indicates the number of colors to use (2, 4, or 8)\n");
  361.     printf("\t-abczefgh followed by num sets the parameter value to num\n");
  362.     printf("\t\tin the system of parametric equations\n\n");
  363.     printf("\t\tx = a*sin(b*t) + c*cos(z*t) and\n");
  364.     printf("\t\ty = e*sin(f*t) + g*cos(h*t)\n\n");
  365. }
  366.  
  367. setcolors()
  368. {
  369.     color2 = color + 1;
  370.     if (color2 == numcolors)
  371.         color2=2;
  372.     color3 = color2 + 1;
  373.     if (color3 == numcolors)
  374.         color3=2;
  375.     color4 = color3 + 1;
  376.     if (color4 == numcolors)
  377.         color4=2;
  378.     color5 = color4 + 1;
  379.     if (color5 == numcolors)
  380.         color5=2;
  381.     color6 = color5 + 1;
  382.     if (color6 == numcolors)
  383.         color6=2;
  384.     color7 = color6 + 1;
  385.     if (color7 == numcolors)
  386.         color7=2;
  387.     color8 = color7 + 1;
  388.     if (color8 == numcolors)
  389.         color8=2;
  390. }
  391.  
  392. setline()
  393. {
  394.     switch(ncols)
  395.     {
  396.     case 2:
  397.         if (slope > 0)
  398.             line_color = color;
  399.         else
  400.             line_color = color2;
  401.         break;
  402.     case 4:
  403.         if (slope > 1.0)
  404.             line_color = color2;
  405.         else if (slope > 0)
  406.             line_color = color;
  407.         else if (slope < -1.0)
  408.             line_color = color3;
  409.         else
  410.             line_color = color4;
  411.         break;
  412.     case 8:
  413.         if (slope > 2.0)
  414.             line_color = color4;
  415.         else if (slope > 1.0)
  416.             line_color = color3;
  417.         else if (slope > 0.5)
  418.             line_color = color2;
  419.         else if (slope > 0.0)
  420.             line_color = color;
  421.         else if (slope < -2.0)
  422.             line_color = color5;
  423.         else if (slope < -1.0)
  424.             line_color = color6;
  425.         else if (slope < -0.5)
  426.             line_color = color7;
  427.         else
  428.             line_color = color8;
  429.         break;
  430.     default:
  431.         sflag=0;
  432.         line_color = color;
  433.         break;
  434.     }
  435. }
  436.  
  437. circ(x,rx)
  438. int x, rx;
  439. {
  440.     int a, y;
  441.     static double d;
  442.     extern double sqrt();
  443.  
  444.     a = ABS(x - rx);
  445.     d = (double)(ABS(Radius-(a*a)));
  446.     y = (int)sqrt(d);
  447.     return(y);
  448. }
  449.  
  450. XtEventHandler
  451. getkey(w, client_data, event)
  452. Widget w;
  453. caddr_t client_data;
  454. XKeyEvent *event;
  455. {
  456.     switch(XLookupKeysym(event, 0))
  457.     {
  458.     case XK_Q:
  459.     case XK_q:            /* quit */
  460.         XtCloseDisplay(dpy);
  461.         exit(0);
  462.         break;
  463.     case XK_e:            /* clear screen  */
  464.         clear(canvas, NULL);
  465.         break;
  466.     case XK_d:            /* toggle erase */
  467.         eflag=(!eflag);
  468.         break;
  469.     case XK_p:            /* toggle pause */
  470.         Pflag=(!Pflag);
  471.         break;
  472.     }
  473. }
  474.  
  475. in_window() {
  476.  
  477.     if (xy[0] > width)
  478.         return(0);
  479.     if (xy[0] < 0)
  480.         return(0);
  481.     if (xy[2] > width)
  482.         return(0);
  483.     if (xy[2] < 0)
  484.         return(0);
  485.     if (xy[1] > height)
  486.         return(0);
  487.     if (xy[1] < 0)
  488.         return(0);
  489.     if (xy[3] > height)
  490.         return(0);
  491.     if (xy[3] < 0)
  492.         return(0);
  493.     return(1);
  494. }
  495.  
  496. parseargs(argc, argv)
  497. int argc;
  498. char *argv[];
  499. {
  500.     char ch; 
  501.     extern int optind;
  502.     extern long atol();
  503.     extern char *optarg;
  504.     while((ch=getopt(argc,argv,
  505.         "uADELPRSn:T:N:C:H:I:W:Z:a:b:c:z:e:f:g:h:p:s:")) !=EOF)
  506.     {    switch(ch)
  507.         {
  508.         case 's':
  509.             sflag++;
  510.             ncols = atoi(optarg);
  511.             if ((ncols != 2) && (ncols != 4) && (ncols != 8)) {
  512.                 printf("madness: -s flag must be followed by 2, 4, or 8\n");
  513.                 exit(2);
  514.             }
  515.             break;
  516.         case 'u':
  517.             usage();
  518.             exit(1);
  519.             break;
  520.         case 'n':
  521.             nsteps = atol(optarg);
  522.             break;
  523.         case 'a':
  524.             a = atof(optarg);
  525.             c = 1.0 - ABS(a);
  526.             break;
  527.         case 'b':
  528.             b = atof(optarg);
  529.             break;
  530.         case 'c':
  531.             c = atof(optarg);
  532.             a = 1.0 - ABS(c);
  533.             break;
  534.         case 'z':
  535.             d = atof(optarg);
  536.             break;
  537.         case 'e':
  538.             e = atof(optarg);
  539.             g = 1.0 - ABS(e);
  540.             break;
  541.         case 'f':
  542.             f = atof(optarg);
  543.             break;
  544.         case 'g':
  545.             g = atof(optarg);
  546.             e = 1.0 - ABS(g);
  547.             break;
  548.         case 'h':
  549.             h = atof(optarg);
  550.             break;
  551.         case 'A':
  552.             heart++;
  553.             break;
  554.         case 'C':
  555.             cflag++;
  556.             parameter = *optarg;
  557.             break;
  558.         case 'D':
  559.             Dflag++;
  560.             break;
  561.         case 'E':
  562.             eflag--;
  563.             break;
  564.         case 'H':
  565.             height = atoi(optarg);
  566.             break;
  567.         case 'I':
  568.             stepsiz = atof(optarg);
  569.             break;
  570.         case 'L':
  571.             logspiral++;
  572.             break;
  573.         case 'N':
  574.             num_pics = atoi(optarg);
  575.             break;
  576.         case 'P':
  577.             Pflag++;
  578.             break;
  579.         case 'R':
  580.             rotate++;
  581.             break;
  582.         case 'S':
  583.             spiral++;
  584.             break;
  585.         case 'T':
  586.             THETA = M_PI/(atof(optarg));
  587.             break;
  588.         case 'W':
  589.             width = atoi(optarg);
  590.             break;
  591. #ifdef USE_DELAY
  592.         case 'Z':
  593.             delay = atoi(optarg);
  594.             break;
  595. #endif
  596.         case 'p':
  597.             prob = atoi(optarg);
  598.             break;
  599.         case '?':
  600.             usage();
  601.             exit(1);
  602.             break;
  603.         }
  604.     }
  605.     if (argc-optind != 0) {
  606.         usage();
  607.         exit(1);
  608.     }
  609.     if (Dflag) {
  610.         if (nsteps == MAXLONG)
  611.             nsteps = 10000;
  612.         if (num_pics == MAXSHORT)
  613.             num_pics = 1;
  614.     }
  615. }
  616.  
  617. void
  618. init_values() {
  619.  
  620.     x_center = width / 2;
  621.     y_center = height / 2;
  622.     if (heart) {
  623.         hmid = x_center;
  624.         hstart = 2*hmid/3;
  625.         hend = hmid + (hmid/3);
  626.         xwid = (hend - hstart)/(2+2*M_SQRT2);
  627.         Radius = xwid*xwid + xwid*xwid;
  628.         x0 = hmid - xwid;
  629.         x1 = hmid + xwid;
  630.         stepsiz = 1.0;
  631.     }
  632. }
  633.  
  634. init_motif(argc, argv)
  635. int argc;
  636. char *argv[];
  637. {
  638.     Widget toplevel;
  639.     int i, j;
  640.     char wname[256];
  641.     static XtResource resource[] = {
  642.     { "appDefaultsFileInstalled" , "AppDefaultsFileInstalled", XtRBoolean,
  643.         sizeof(Boolean), 0, XtRString, "False" } };
  644.  
  645.     toplevel = XtInitialize(argv[0], "Madness", NULL, 0, &argc, argv);
  646.     framework = XtCreateManagedWidget("framework",
  647.              xmFormWidgetClass, toplevel, NULL, 0);
  648.     /*
  649.     * Create the canvas widget to display the madness
  650.     */
  651.     canvas = XtCreateManagedWidget("drawing_canvas",
  652.            xmDrawingAreaWidgetClass, framework, NULL, 0);
  653.     dpy = XtDisplay(canvas);
  654.     screen = XtScreen(canvas);
  655.     /*
  656.     * Create the pushbutton widgets.
  657.     */
  658.     button[0] =  XtCreateManagedWidget("go_button",
  659.                 xmPushButtonWidgetClass,
  660.                 framework, NULL, 0);
  661.     button[1] =  XtCreateManagedWidget("next_button",
  662.                 xmPushButtonWidgetClass,
  663.                 framework, NULL, 0);
  664.     button[2] =  XtCreateManagedWidget("clear_button",
  665.                 xmPushButtonWidgetClass,
  666.                 framework, NULL, 0);
  667.     button[3] =  XtCreateManagedWidget("quit_button",
  668.                 xmPushButtonWidgetClass,
  669.                 framework, NULL, 0);
  670.     init_data();
  671.     init_canvas();
  672.     init_values();
  673.     srand((int)time(0));
  674.     /*
  675.     * Add callbacks.
  676.     */
  677.     XtAddCallback(button[0],XmNactivateCallback,start_iterate,NULL);
  678.     XtAddCallback(button[1],XmNactivateCallback,next_color,NULL);
  679.     XtAddCallback(button[2], XmNactivateCallback, clear, NULL);
  680.     XtAddCallback(button[3], XmNactivateCallback, quit, NULL);
  681.     XtRealizeWidget(toplevel);
  682.     /* Title */
  683.     sprintf((char *) wname, "Madness by Ron Record");
  684.      XChangeProperty(dpy, XtWindow(toplevel), XA_WM_NAME, XA_STRING, 8, 
  685.          PropModeReplace, wname, strlen(wname));
  686.     XtAddCallback(canvas, XmNresizeCallback, resize, NULL);
  687.     XtAddEventHandler(framework, KeyPressMask, FALSE, getkey, NULL);
  688.     XtAddEventHandler(button[0], KeyPressMask, FALSE, getkey, NULL);
  689.     XtAddEventHandler(button[1], KeyPressMask, FALSE, getkey, NULL);
  690.     XtAddEventHandler(button[2], KeyPressMask, FALSE, getkey, NULL);
  691.     XtAddEventHandler(button[3], KeyPressMask, FALSE, getkey, NULL);
  692.     resize(canvas, NULL, NULL);
  693.     work_proc_id = XtAddWorkProc(draw_madness, canvas);
  694.     XtGetApplicationResources(toplevel, &appDefaultsFileInstalled, resource,
  695.             1, NULL, 0);
  696.     if (!appDefaultsFileInstalled)
  697.         fprintf(stderr, 
  698.                 "Warning: the Madness app-defaults file is not installed\n");
  699. }
  700.  
  701. init_data()
  702. {
  703.     long pid;
  704.         extern void srand48();
  705.  
  706.     numcolors = XDisplayCells(dpy, XDefaultScreen(dpy));
  707.     numcolors = Min(numcolors, MAXCOLOR) - 1;
  708.     pid = getpid();
  709.     srand(pid);
  710.     srand48(pid);
  711.     hcolor = color = (rand() % (numcolors-2))+2;
  712.     if (numcolors < 10)
  713.         sflag--;
  714.     if (sflag)
  715.         setcolors();
  716. }
  717.  
  718. init_canvas()
  719. {
  720.     Arg wargs[2];
  721.     static int i;
  722.  
  723.     /*
  724.     * Set the size of the drawing areas.
  725.     */
  726.     if (width == 0)
  727.         width = XDisplayWidth(dpy, DefaultScreen(dpy));
  728.     if (height == 0)
  729.         height = XDisplayHeight(dpy, DefaultScreen(dpy));
  730.     if (MIN_WIDTH > width)
  731.         width = MIN_WIDTH;
  732.     if (MIN_HEIGHT > height)
  733.         height = MIN_HEIGHT;
  734.     XtSetArg(wargs[0], XtNwidth, width);
  735.     XtSetArg(wargs[1], XtNheight, height);
  736.     XtSetValues(framework, wargs,2);
  737.     /*
  738.     * create default, writable, graphics contexts for the canvas.
  739.     */
  740.     for (i=0; i<MAXCOLOR; i++) {
  741.         Data_GC[i] = XCreateGC(dpy, DefaultRootWindow(dpy), 0, 
  742.                 (XGCValues *)NULL);
  743.         /* set the background to black */
  744.         XSetBackground(dpy, Data_GC[i], 
  745.             BlackPixel(dpy, XDefaultScreen(dpy)));
  746.         /* set the foreground of the i'th context to i */
  747.         XSetForeground(dpy, Data_GC[i], i);
  748.     }
  749. }
  750.  
  751. void
  752. resize(w, data, call_data)
  753. Widget     w;
  754. struct image_data    *data;
  755. caddr_t    call_data;
  756. {
  757.     static Arg wargs[2];
  758.     static Dimension W=0, H=0;
  759.     /*
  760.     *   Get the new window size.
  761.     */
  762.     XtSetArg(wargs[0], XtNwidth,  &W);
  763.     XtSetArg(wargs[1], XtNheight, &H);
  764.     XtGetValues(w, wargs, 2);
  765.     /* recalculate offsets */
  766.     width = (int)W; height = (int)H;
  767.     init_values();
  768.     /*
  769.     * Clear the window.
  770.     */
  771.     clear(canvas, NULL);
  772.     setup();
  773. }
  774.  
  775. void
  776. start_iterate(w, call_data)
  777. Widget w;
  778. XmAnyCallbackStruct *call_data;
  779. {
  780.     XmString label;
  781.     Arg wargs[1];
  782.  
  783.     if (work_proc_id) {
  784.         XtRemoveWorkProc(work_proc_id);
  785.         work_proc_id = (XtWorkProcId)NULL;
  786.         label = XmStringCreate("RESUME",XmSTRING_DEFAULT_CHARSET);
  787.         XtSetArg(wargs[0], XmNlabelString, label);
  788.         XtSetValues(button[0], wargs, 1);
  789.     }
  790.     else {
  791.         /*
  792.         * Register draw_madness() as a WorkProc.
  793.         */
  794.         work_proc_id = XtAddWorkProc(draw_madness, canvas);
  795.         label = XmStringCreate("PAUSE",XmSTRING_DEFAULT_CHARSET);
  796.         XtSetArg(wargs[0], XmNlabelString, label);
  797.         XtSetValues(button[0], wargs, 1);
  798.     }
  799. }
  800.  
  801. void
  802. next_color(w, call_data)
  803. Widget w;
  804. XmAnyCallbackStruct  *call_data;
  805. {
  806.         line_color = hcolor = color = (rand() % (numcolors-2))+2;
  807.         if (numcolors < 10)
  808.             sflag--;
  809.         if (sflag)
  810.             setcolors();
  811. }
  812.  
  813. void
  814. clear(w, call_value)
  815. Widget w;
  816. XmAnyCallbackStruct *call_value;
  817. {
  818.     if(XtIsRealized(canvas))
  819.         XClearArea(dpy, XtWindow(canvas), 0, 0, 0, 0, TRUE);
  820. }
  821.  
  822. void
  823. quit(w, call_value)
  824. Widget w;
  825. XmAnyCallbackStruct *call_value;
  826. {
  827.     XtCloseDisplay(dpy);
  828.     exit(0);
  829. }
  830.